package muyu;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;

import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 千山鸟飞绝，万径人踪灭。
 * 孤舟蓑笠翁，独钓寒江雪。
 *
 * @author: 于其先
 * @date: 2017/11/2
 * @version: 1.0.0
 */
public class ExtendUtils {
    protected static Logger logger = LoggerFactory.getLogger(ExtendUtils.class);

    /**
     * 下划线转驼峰
     *
     * @param line
     * @param smallCamel 首字符是否小写
     * @return
     */
    public static String underline2Camel(String line, boolean smallCamel) {
        if (line == null || "".equals(line)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        final Pattern pattern = Pattern.compile("([A-Za-z\\d]+)(_)?");
        Matcher matcher = pattern.matcher(line);
        while (matcher.find()) {
            String word = matcher.group();
            sb.append(smallCamel && matcher.start() == 0 ? Character.toLowerCase(word.charAt(0)) : Character.toUpperCase(word.charAt(0)));
            int index = word.lastIndexOf('_');
            if (index > 0) {
                sb.append(word.substring(1, index).toLowerCase());
            } else {
                sb.append(word.substring(1).toLowerCase());
            }
        }
        return sb.toString();
    }

    /**
     * 驼峰转下划线
     *
     * @param line
     * @return
     */
    public static String camel2Underline(String line) {
        if (line == null || "".equals(line)) {
            return "";
        }
        line = String.valueOf(line.charAt(0)).toUpperCase().concat(line.substring(1));
        StringBuilder sb = new StringBuilder();
        final Pattern pattern = Pattern.compile("[A-Z]([a-z\\d]+)?");
        Matcher matcher = pattern.matcher(line);
        while (matcher.find()) {
            String word = matcher.group();
            sb.append(word.toUpperCase());
            sb.append(matcher.end() == line.length() ? "" : "_");
        }
        return sb.toString();
    }


    public static String getFileExtension(String fileName) {
        String extendName;
        if ((fileName == null) || (fileName.lastIndexOf(".") == -1) || (fileName.lastIndexOf(".") == fileName.length() - 1)) {
            extendName = null;
        } else {
            extendName = StringUtils.lowerCase(fileName.substring(fileName.lastIndexOf(".") + 1));
        }

        return extendName;
    }

    /**
     * 获取对象的空属性
     *
     * @param source
     * @param ignoreEmptyString
     * @return
     */
    public static String[] getNullProps(Object source, boolean ignoreEmptyString) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] propertyDescriptors = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();

        for (PropertyDescriptor propDesc : propertyDescriptors) {

            Object srcValue = src.getPropertyValue(propDesc.getName());
            if (srcValue == null) {
                emptyNames.add(propDesc.getName());
            } else {
                //如果是空字符串，同样不合并。
                if (srcValue instanceof String) {
                    if (StringUtils.isBlank((String) srcValue) && ignoreEmptyString) {
                        emptyNames.add(propDesc.getName());
                    }
                }
            }
        }

        return emptyNames.toArray(new String[emptyNames.size()]);
    }

    /**
     * 复制属性只忽略null
     *
     * @param source
     * @param target
     * @throws BeansException
     */
    public static void copyPropertiesIgnoreNull(Object source, Object target) throws BeansException {
        BeanUtils.copyProperties(source, target, ExtendUtils.getNullProps(source, false));
    }

    /**
     * 复制属性忽略NULL和空字符串
     *
     * @param source
     * @param target
     * @throws BeansException
     */
    public static void copyPropertiesIgnoreEmpty(Object source, Object target) throws BeansException {
        BeanUtils.copyProperties(source, target, ExtendUtils.getNullProps(source, true));
    }

    /**
     * 获取类以及其父类的所有属性
     *
     * @param clz
     * @return
     */
    public static List<String> getClassFields(Class clz) {
        List<Field> fieldList = new ArrayList<>();
        Class tempClass = clz;
        while (tempClass != null) {
            fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass();
        }

        return fieldList.stream().map(Field::getName).collect(Collectors.toList());
    }

    /**
     * 递归创建目录
     *
     * @param file
     */
    public static boolean mkDir(File file) {
        if (file.getParentFile().exists()) {
            return file.mkdir();
        } else {
            return mkDir(file.getParentFile()) && file.mkdir();
        }
    }

    /**
     * 确保目录存在
     *
     * @param dirName
     * @return
     */
    public static boolean ensureDir(String dirName) {
        return mkDir(new File(dirName));
    }

    public static void rm(String fileName) {
        File file = new File(fileName);
        if (file.exists()) {
            if (file.isFile()) {
                file.delete();
            } else {
                delDir(fileName);
            }
        }
    }

    public static void delDir(String path) {
        File dir = new File(path);
        if (dir.exists()) {
            File[] tmp = dir.listFiles();
            for (File file : tmp) {
                if (file.isDirectory()) {
                    delDir(path + "/" + file.getName());
                } else {
                    file.delete();
                }
            }
            dir.delete();
        }
    }

    public static boolean moveTo(String fileName,String dstFileName){
        File file = new File(fileName);
        return file.renameTo(new File(dstFileName));
    }

    public static void  callCmd(String locationCmd) throws IOException{
        logger.debug(locationCmd);

        StringBuilder sb    = new StringBuilder();
        Process child       = Runtime.getRuntime().exec(locationCmd);
        InputStream in      = child.getInputStream();

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
        String line;
        while((line = bufferedReader.readLine())!=null) {
            sb.append(line).append("\n");
        }

        in.close();
//        child.waitFor();

        logger.debug("sb:" + sb.toString());
        logger.debug("callCmd execute finished");
    }

    /**
     * 将字符串首字母大写
     *
     * @param str
     * @return
     */
    public static String upperCase(String str) {
        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0] - 32);
        }
        return new String(ch);
    }

    /**
     * 将字符串首字母小写
     *
     * @param str
     * @return
     */
    public static String lowerCase(String str) {
        char[] ch = str.toCharArray();
        if (ch[0] >= 'A' && ch[0] <= 'Z') {
            ch[0] = (char) (ch[0] + 32);
        }
        return new String(ch);
    }

    public static BigDecimal getVal(BigDecimal val) {
        return val == null ? BigDecimal.ZERO : val;
    }


    public static String getValue(String[] array, int pos) {
        return array == null || array.length <= pos || StringUtils.isBlank(array[pos]) ? null : array[pos];
    }
}
